/**
 * This class contains the rest of the implementation of the
 * matrix operations, in this case for the dense representation.
 * 
 * Representational invariants:
 * The matrix entries are stored directly in a full matrix.
 * 
 * !!!!! Do not add any additional public or protected methods
 * or variables to this class.  You may add any PRIVATE variables
 * or methods as you see necessary, but do not add any additional
 * major data structures. !!!!!
 */

/*
 * Author: Yuan Li
 * Titile: 15121 summer 2011 lab3
 * Date: Aug 13 2011
 */
public class DenseMatrix extends AbstractMatrix
{
	
	/* Hold the data of the matrix */
	private double[][] data;
	
	/**
	 * checkRowsCols -- will check whether the numbers of row and col are invalid 
	 * @param row specific row
	 * @param col specific col
	 * @throws IllegalArgumentException if the rows or cols are invalid
	 */
	private void checkRowsCols(int row, int col){
		if (this.getRows() < 0 || this.getCols() < 0){
			throw new IllegalArgumentException("The rows and cols of the matrix should not be negtive");
		}
	}
	
	/**
	 * checkRowCol -- will check whether row or col is invalid
	 * @param row specific row
	 * @param col specific col
	 * @throws IllegalArgumentException if the row or col is invalid
	 */
	private void checkRowCol(int row, int col){
		if (row < 0 || row >= this.getRows() || col < 0 || col >= this.getCols()){
			throw new IllegalArgumentException("Invalid row or col for the matrix!!");
		}
	}
	
	public void clear()
	{
		// check the validation of the cols and rows
		checkRowsCols(this.getRows(),this.getCols());
		
		// initialize a 2D array to present a matrix
		this.data = new double[this.getRows()][this.getCols()];
		for (int row=0; row < this.getRows(); row++){
			for (int col=0; col < this.getCols(); col++){
				this.set(row, col, 0);
			}		
		}
		//throw new RuntimeException("You must implement this method!");
	}
	
	
	
	public double get(int row, int col)
	{
		checkRowCol(row, col);
		
		return this.data[row][col];
		//throw new RuntimeException("You must implement this method!");
	}
	
	public void set(int row, int col, double val)
	{
		checkRowCol(row, col);
		
		this.data[row][col] = val;
		//throw new RuntimeException("You must implement this method!");
	}
	
	public double[] getRow(int row)
	{
		// check the validation of the row
		if (row < 0 || row >= this.getRows()){
			throw new IllegalArgumentException("the row is invalid for getRow()");
		}
		
		/* we will not use ligtht copy, because this will expose our internal array to outsider to modify
		return this.data[row];
		*/
		
		// instead we duplicate a array, make a deep copy, this may affects the speed but it is safe for us
		double[] tmp = new double[this.getRows()];
		for (int col=0; col < this.getCols(); col++){
			tmp[col] = this.get(row, col);
		}
		
		return tmp;
		//throw new RuntimeException("You must implement this method!");
	}
	
	public double[] getCol(int col)
	{
		// check the validation of the col
		if (col < 0 || col >= this.getCols()){
			throw new IllegalArgumentException("the col is invalid for getCol()");
		}
		
		double[] tmp = new double[this.getRows()];
		for (int row=0; row < this.getRows(); row++){
			tmp[row] = this.get(row, col);
		}
		
		return tmp;
		//throw new RuntimeException("You must implement this method!");
	}
	
	public double rowSum(int row)
	{
		// check the validation of the row
		if (row < 0 || row >= this.getRows()){
			throw new IllegalArgumentException("the row is invalid for rowSum()");
		}
		
		double sum = 0;
		for (int col=0; col < this.getCols(); col++){
			sum = sum + this.get(row, col);
		}
		
		return sum;
		//throw new RuntimeException("You must implement this method!");
	}
	
	public double colSum(int col)
	{
		// check the validation of the col
		if (col < 0 || col >= this.getCols()){
			throw new IllegalArgumentException("the col is invalid for colSum()");
		}
		
		double sum = 0;
		
		for (int row=0; row < this.getRows(); row++){
			sum = sum + this.get(row, col);
		}
		
		return sum;
		//throw new RuntimeException("You must implement this method!");
	}
	
	public boolean checkRepresentation()
	{
		return true;
	}

}
